(function() {
    //定义当前使用的开源组建的版本号
    var OPEN_JS_T = {
        Jpegmeta: "201508011808",
        JpegEncoder: "201508011808",
        ImageCompress: "201508011808"
    };

    var uploadObj;
    window.photo = {

        maxUpload: 8,
        // 上传信息 主要是 id 对应信息
        uploadInfo: {},
        // 上传队列，里面保存的是 id
        uploadQueue: [],
        // 预览队列，里面保存的是 id
        previewQueue: [],
        // 请求对象
        xhr: {},
        // 是否有任务正在上传
        isBusy: false,
        // fid
        fid: 0,
        tid: 0,
        pId: 0,
        qunId: 0,

        countUpload: function() {
            var num = 0;
            $.each(photo.uploadInfo, function(i, n) {
                if (n) {
                    ++num;
                }
            });

            return num;
        },

        getbuilder: function(s, filename, filedata, boundary) {
            var dashdash = '--',
                crlf = '\r\n',
                builder = '';

            for (var i in s.uploadformdata) {
                builder += dashdash;
                builder += boundary;
                builder += crlf;
                builder += 'Content-Disposition: form-data; name="' + i + '"';
                builder += crlf;
                builder += crlf;
                builder += s.uploadformdata[i];
                builder += crlf;
            }

            builder += dashdash;
            builder += boundary;
            builder += crlf;
            builder += 'Content-Disposition: form-data; name="' + s.uploadinputname + '"';
            builder += '; filename="' + filename + '"';
            builder += crlf;

            builder += 'Content-Type: application/octet-stream';
            builder += crlf;
            builder += crlf;

            builder += filedata;
            builder += crlf;

            builder += dashdash;
            builder += boundary;
            builder += dashdash;
            builder += crlf;
            return builder;
        },
        has_upload_list: function(ul, act) {
            var textarea = ul.prev();
            var lis = $(ul).find("li");
            var imgList = new Array();
            $.each(lis, function(i, v) {
                var imgs = {};
                if ($(v).attr("url")) {
                    imgs['file_url'] = $(v).attr("url");
                    imgs['file_name'] = $(v).attr("name");
                    imgList.push(imgs);
                }
            })
            if (imgList.length > 0) {
                textarea.val(JSON.stringify(imgList));
            } else {
                textarea.val("");
            }
            if (act == "del") {
                textarea.trigger("BoxUploadDel");
            }
            if (act == "add") {
                textarea.trigger("BoxUploadAdd");
            }
            console.log(textarea.val());
        },
        // 图片预览
        uploadPreview: function(id) {

            var reader = new FileReader();
            var uploadBase64;
            var conf = {},
                file = photo.uploadInfo[id].file;

            reader.onload = function(e) {
                var result = this.result;

                // 如果是jpg格式图片，读取图片拍摄方向,自动旋转
                if (file.type == 'image/jpeg') {
                    var jpg = new JpegMeta.JpegFile(result, file.name);
                    if (jpg.tiff && jpg.tiff.Orientation) {

                        conf = {
                            maxW: 800, //目标宽
                            maxH: 800, //目标高
                            quality: 0.8, //目标jpg图片输出质量
                            orien: 1
                        };
                        //设置旋转
                        var Orientation=jpg.tiff.Orientation.value;
                        if(Orientation != "" && Orientation != 1){  
                                conf['orien']=jpg.tiff.Orientation.value;
                        }           
                    }
                }

                // 压缩
                if (ImageCompresser.support()) {
                    var img = new Image();
                    img.onload = function() {
                        try {
                            uploadBase64 = ImageCompresser.getImageBase64(this, conf);
                        } catch (e) {
                            //TOOLS.dialog({content:'压缩图片失败',autoClose:true});
                            $('li#li' + id).remove();
                            return false;
                        }
                        if (uploadBase64.indexOf('data:image') < 0) {
                            // TOOLS.dialog({content:'上传照片格式不支持',autoClose:true});
                            $('li#li' + id).remove();
                            return false;
                        }

                        photo.uploadInfo[id].file = uploadBase64; //e.target.result;
                        photo.uploadInfo[id].filename = file.name;
                        $('li#li' + id).find('img').attr('src', uploadBase64);
                        photo.uploadQueue.push(id);
                    }
                    img.src = ImageCompresser.getFileObjectURL(file);
                } else {
                    uploadBase64 = result;
                    if (uploadBase64.indexOf('data:image') < 0) {
                        // TOOLS.dialog({content:'上传照片格式不支持',autoClose:true});
                        $('li#li' + id).remove();
                        return false;
                    }
                    photo.uploadInfo[id].file = uploadBase64; //e.target.result;
                    photo.uploadInfo[id].filename = file.name;
                    $('li#li' + id).find('img').attr('src', uploadBase64);
                    photo.uploadQueue.push(id);
                }

            }
            reader.readAsBinaryString(photo.uploadInfo[id].file);
        },

        _keys: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
        /*用于BASE64转码*/

        base64decode: function(input) {
            var output = '';
            var chr1, chr2, chr3 = '';
            var enc1, enc2, enc3, enc4 = '';
            var i = 0;
            if (input.length % 4 != 0) {
                return '';
            }
            var base64test = /[^A-Za-z0-9\+\/\=]/g;
            if (base64test.exec(input)) {
                return '';
            }
            do {
                enc1 = photo._keys.indexOf(input.charAt(i++));
                enc2 = photo._keys.indexOf(input.charAt(i++));
                enc3 = photo._keys.indexOf(input.charAt(i++));
                enc4 = photo._keys.indexOf(input.charAt(i++));
                chr1 = (enc1 << 2) | (enc2 >> 4);
                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                chr3 = ((enc3 & 3) << 6) | enc4;
                output = output + String.fromCharCode(chr1);
                if (enc3 != 64) {
                    output += String.fromCharCode(chr2);
                }
                if (enc4 != 64) {
                    output += String.fromCharCode(chr3);
                }
                chr1 = chr2 = chr3 = '';
                enc1 = enc2 = enc3 = enc4 = '';
            } while (i < input.length);
            return output;
        },

        // 创建上传请求
        createUpload: function(id, act) {

            if (!photo.uploadInfo[id]) {
                return false;
            }

            var path = $('li#li' + id).parent().attr("path");
            var exts = $('li#li' + id).parent().attr("exts");
            if (typeof(exts) == "undefined") exts = "";
            if (typeof(path) == "undefined") path = "";
            // 图片posturl
            var uploadUrl = '/BoxAddon/Upload/Index/upload/exts/' + exts + "/path/" + path; //alert(uploadUrl);
            //console.log(uploadUrl);
            $('li#li' + id).prepend('<div class="maskLay"></div>');
            // 产生进度条
            var progressHtml = '<div class="progress" id="progress' + id + '"><div class="proBar" style="width:0%;"></div></div>';
            //$('li#li' + id).prepend(progressHtml);
            $('li#li' + id).find('.maskLay').insertAfter(progressHtml);
            //var formData = new FormData();
            // formData.append('filedata', photo.uploadInfo[id].file);
            // formData.append('uid', uid); 
            /*formData.append('tid', topicid);
        formData.append('hash', uploadHash);
        formData.append('token', S_token);*/

            var progress = function(e) {
                if (e.target.response) {
                    var result = $.parseJSON(e.target.response);
                    if (result.errCode != 0) {
                        // $('#message').val(result.errCode);
                        //TOOLS.dialog({content:'网络不稳定，请稍后重新操作',autoClose:true});
                        removePic(id);
                    }
                }

                var progress = $('#progress' + id).find('.proBar');
                if (e.total == e.loaded) {
                    var percent = 100;
                } else {
                    var percent = 100 * (e.loaded / e.total);
                }
                // 控制进度条不要超出
                if (percent > 100) {
                    percent = 100;
                }
                progress.css('width', percent + '%');

                if (percent == 100) {
                    $('li#li' + id).find('.maskLay').remove();
                    $('li#li' + id).find('.progress').remove();
                }
            }

            var removePic = function(id) {
                donePic(id);
                $('li#li' + id).remove();
                var ul = $('li#li' + id).parent();
                photo.has_upload_list(ul, "del");
            }

            var donePic = function(id) {
                photo.isBusy = false;
                photo.uploadInfo[id].isDone = true;
                photo.xhr[id] = null;

                /*var reportObj = {
                    'a' : 'upload',
                    'uid' : uid || ''
                };
                TOOLS.addReportCount(reportObj);*/
            }

            var complete = function(e) {
                //TOOLS.dialog({content:e.target.response,autoClose:true});
                // 上传结束
                donePic(id);
                /*
                 返回值(纯文本) 如：DB|0|1051301|1|0
                 DB为固定输出
                 第一个0   代表报错信息，0为正常，非零为出错。
                 第二个1051301 代表成功上传图片的附件aid
                 第三个1   代表是否是图片
                 第四个0   代表导致出错的上传文件容量的尺寸，比如1024000,则限制1024000字节以下的
                 */
                //alert(e.target.response);
                //console.log(e);
                var response = JSON.parse(e.target.response);
                console.log(response);
                //if(response.error)
                //  var attach = response.msg.split('|')
                //console.log(attach);
                //alert(attach.length);
                if (response.error == 0) {
                    var obj = $('li#li' + id);
                    obj.attr("name", response.data.name);
                    obj.attr("url", response.data.file_url);
                    obj.append('<input type="hidden" name="imgList['+id+'][name]" value="'+response.data.name+'" />');
                    obj.append('<input type="hidden" name="imgList['+id+'][file_url]" value="'+response.data.file_url+'" />');
                    $('li#li' + id).find('.maskLay').remove();
                    $('li#li' + id).find('.progress').remove();
                    photo.has_upload_list($(obj).parent(), "add");
                } else {
                    hiApp.alert(response.msg);
                    removePic(id);
                }

            }



            var failed = function() {
                photo.isBusy = false;
                photo.uploadInfo[id].isDone = true;
                //TOOLS.dialog({content:'网络断开，请稍后重新操作',autoClose:true});
                removePic(id)
            }

            var abort = function() {
                photo.isBusy = false;
                photo.uploadInfo[id].isDone = true;
                //TOOLS.dialog({content:'上传已取消',autoClose:true});
                removePic(id)
            }

            // 创建 ajax 请求
            photo.xhr[id] = new XMLHttpRequest();
            var boundary = '------multipartformboundary' + (new Date).getTime();
            var s = {
                uploadformdata: { qunid: photo.qunId, topicid: photo.tid },
                uploadinputname: 'filedata',
            };

            var picdata = photo.uploadInfo[id].file.replace(/data:.+;base64,/, '');
            if (typeof atob == 'function') {
                picdata = atob(picdata);
            } else {
                picdata = photo.base64decode(picdata);
            }
            var builder = photo.getbuilder(s, photo.uploadInfo[id].filename, picdata, boundary);
            photo.xhr[id].open("POST", uploadUrl, true);
            photo.xhr[id].setRequestHeader('content-type', 'multipart/form-data; boundary=' + boundary);
            if (!XMLHttpRequest.prototype.sendAsBinary) { //如果XMLHttpRequest没有sendAsBinary
                XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
                    function byteValue(x) {
                        return x.charCodeAt(0) & 0xff;
                    }
                    var ords = Array.prototype.map.call(datastr, byteValue);
                    var ui8a = new Uint8Array(ords);
                    this.send(ui8a.buffer);
                };
            }
            photo.xhr[id].sendAsBinary(builder);
            photo.xhr[id].onerror = function(e) {
                failed();
            };
            photo.xhr[id].onload = function(e) {
                complete(e);
            };
            photo.xhr[id].abort = function(e) {
                abort();
            };
            photo.xhr[id].onsendstream = function(e) {
                progress(e);
            };

        },

        initUpload: function(_this) {
            var html = '<ul class="photoList-content" >';
            html += '<li class="add-image" style="position:relative">+';
            html += '<input type="file" style="opacity:0; height:100%;width:100%; position:absolute; top:0px; left:0px" id="initUpload" />';
            html += '</li>';
            html += '</ul>';
            _this.html(html);
            var maxUpload=$(_this).attr("upload")?$(_this).attr("upload"):1;
          $(_this).find("#initUpload").unbind("change").bind("change",function(e){
            //  if (photo.isBusy) {
            //     hiApp.alert('上传中，请稍后添加');
            //     return false;
            // }
                uploadObj = $(this);
                var ul = $(this).parents("ul");
                e = e || window.event;
                var fileList = e.target.files;
                if (!fileList.length) {
                    return false;
                }  
                for (var i = 0; i < fileList.length; i++) {
                    var file = fileList[i];

                    if (!photo.checkPicSize(file)) {
                        hiApp.alert('文件体积过大');
                        continue;
                    }
                    if (!photo.checkPicType(file)) {
                        hiApp.alert('上传文件格式不支持');
                        continue;
                    }

                    var id = Date.now() + i;
                    // 增加到上传对象中, 上传完成后，修改为 true
                    photo.uploadInfo[id] = {
                        file: file,
                        filename: '',
                        isDone: false,
                    };

                    var html = '<li id="li' + id + '"><div class="photoCut"><img  class="attchImg" ></div>' +
                        '<div class="maskLay"></div>' +
                        '<a href="javascript:" class="cBtn spr db "  _id="' + id + '">关闭</a></li>';
                    $(html).insertBefore($(this).parents("li"));
                    //删除        
                    $(ul).find(".cBtn").unbind("click").bind("click",function() {
                        
                        var id = $(this).attr('_id');
                        var ul = $(this).parents("ul");
                        var li = $(this).parents("li");
                        // 取消这个请求
                        if (photo.xhr[id]) {
                            photo.xhr[id].abort();
                        }
                        // 图片删除
                        $(li).remove();
                        photo.uploadInfo[id] = null;
                        photo.has_upload_list(ul, "del");
                        if($(ul).find("li").length<maxUpload){
                             // 图片变少了，显示+号
                             $(ul).find("#initUpload").parent().show();
                        }
                    });
                    photo.previewQueue.push(id);
                }
                if($(ul).find("li").length>maxUpload){
                     $(this).parents("li").hide();
                 }
               
                // 把输入框清空
                $(this).val('');
          })
             
            setInterval(function() {
                // 预览
                setTimeout(function() {
                    if (photo.previewQueue.length) {
                        var jobId = photo.previewQueue.shift();
                        photo.uploadPreview(jobId);
                    }
                }, 1);
                // 上传
                setTimeout(function() {
                    if (!photo.isBusy && photo.uploadQueue.length) {
                        var jobId = photo.uploadQueue.shift();
                        photo.isBusy = true;
                        photo.createUpload(jobId, 'topic');
                    }
                }, 10);
            }, 300);

        },

        // 批量上传上传相关
        initMultipleUpload: function() {

            if (!photo.isBusy) {
                $(document).on("touchstart", "#addPic", function() {
                    $('#uploadFile').click();
                });
            } else {
                hiApp.alert('上传中，请稍后添加');
                return false;
            }

            // 文件表单发生变化时
            $(document).on('change', '.uploadFile', function(e) {
                uploadObj = $(this);
                var ul = $(this).parent().parent();
                e = e || window.event;
                var fileList = e.target.files;
                if (!fileList.length) {
                    return false;
                }
                if ($(ul).attr("maxUpload")) {
                    photo.maxUpload = $(ul).attr("maxUpload");
                }
                for (var i = 0; i < fileList.length; i++) {
                    if (photo.countUpload() >= photo.maxUpload) {
                        hiApp.alert('你最多只能上传' + photo.maxUpload + '个文件');
                        break;
                    }

                    var file = fileList[i];

                    if (!photo.checkPicSize(file)) {
                        hiApp.alert('文件体积过大');
                        continue;
                    }
                    // if (!photo.checkPicType(file)) {
                    //             hiApp.alert('上传文件格式不支持');
                    //                continue;
                    //           }

                    var id = Date.now() + i;
                    // 增加到上传对象中, 上传完成后，修改为 true
                    photo.uploadInfo[id] = {
                        file: file,
                        filename: '',
                        isDone: false,
                    };

                    var html = '<li id="li' + id + '"><div class="photoCut"><img src="/Public/images/defaultImg.jpg" class="attchImg" alt="photo"></div>' +
                        '<div class="maskLay"></div>' +
                        '<a href="javascript:" class="cBtn spr db "  _id="' + id + '">关闭</a></li>';
                    $('.photoList').find('ul').prepend(html);
                    photo.previewQueue.push(id);
                }
                // 图片已经上传了 8 张，隐藏 + 号
                if (photo.countUpload() >= photo.maxUpload) {
                    $(this).parent().hide();
                }

                // 把输入框清空
                $(this).val('');
            });

            //删除        
            $('.photoList').on("click", '.cBtn', function() {
                var id = $(this).attr('_id');
                var _this = $(this);
                var ul = $(this).parent().parent();
                var li = $(this).parent();
                // 取消这个请求
                if (photo.xhr[id]) {
                    photo.xhr[id].abort();
                }

                // 图片删除
                $('li#li' + id).remove();
                photo.uploadInfo[id] = null;
                photo.has_upload_list(ul, "del");

                // 图片变少了，显示+号
                if (photo.countUpload() < photo.maxUpload) {
                    $(ul).find(".uploadFile").parent().show();
                }
            });

            setInterval(function() {
                // 预览
                setTimeout(function() {
                    if (photo.previewQueue.length) {
                        var jobId = photo.previewQueue.shift();
                        photo.uploadPreview(jobId);
                    }
                }, 1);
                // 上传
                setTimeout(function() {
                    if (!photo.isBusy && photo.uploadQueue.length) {
                        var jobId = photo.uploadQueue.shift();
                        photo.isBusy = true;
                        photo.createUpload(jobId, 'topic');
                    }
                }, 10);
            }, 300);

        },

        // 检查图片大小
        checkPicSize: function(file) {
            // 8M
            if (file.size > 10000000) {
                return false;
            }
            return true;
        },
        // 检查图片类型
        checkPicType: function(file) {

            if (file.type.indexOf('image/') == 0) {
                return true;
            } else {
                var index = file.name.lastIndexOf('.');
                var extName = file.name.substring(index + 1).toLowerCase();
                if (extName == 'jpg' || extName == 'jpeg' || extName == 'png' || extName == 'gif') {
                    return true;
                }
                return false;
            }
        }

    };

    return photo;
})();

/******jpegmeta.js*******/
var JpegMeta = {};
this.JpegMeta = JpegMeta;
JpegMeta.parseNum = function parseNum(endian, data, offset, size) {
    var i;
    var ret;
    var big_endian = (endian === ">");
    if (offset === undefined) offset = 0;
    if (size === undefined) size = data.length - offset;
    for (big_endian ? i = offset : i = offset + size - 1; big_endian ? i < offset + size : i >= offset; big_endian ? i++ : i--) {
        ret <<= 8;
        ret += data.charCodeAt(i);
    }
    return ret;
};
JpegMeta.parseSnum = function parseSnum(endian, data, offset, size) {
    var i;
    var ret;
    var neg;
    var big_endian = (endian === ">");
    if (offset === undefined) offset = 0;
    if (size === undefined) size = data.length - offset;
    for (big_endian ? i = offset : i = offset + size - 1; big_endian ? i < offset + size : i >= offset; big_endian ? i++ : i--) {
        if (neg === undefined) {
            neg = (data.charCodeAt(i) & 0x80) === 0x80;
        }
        ret <<= 8;
        ret += neg ? ~data.charCodeAt(i) & 0xff : data.charCodeAt(i);
    }
    if (neg) {
        ret += 1;
        ret *= -1;
    }
    return ret;
};
JpegMeta.Rational = function Rational(num, den) {
    this.num = num;
    this.den = den || 1;
    return this;
};
JpegMeta.Rational.prototype.toString = function toString() {
    if (this.num === 0) {
        return "" + this.num;
    }
    if (this.den === 1) {
        return "" + this.num;
    }
    if (this.num === 1) {
        return this.num + " / " + this.den;
    }
    return this.num / this.den;
};
JpegMeta.Rational.prototype.asFloat = function asFloat() {
    return this.num / this.den;
};
JpegMeta.MetaGroup = function MetaGroup(fieldName, description) {
    this.fieldName = fieldName;
    this.description = description;
    this.metaProps = {};
    return this;
};
JpegMeta.MetaGroup.prototype._addProperty = function _addProperty(fieldName, description, value) {
    var property = new JpegMeta.MetaProp(fieldName, description, value);
    this[property.fieldName] = property;
    this.metaProps[property.fieldName] = property;
};
JpegMeta.MetaGroup.prototype.toString = function toString() {
    return "[MetaGroup " + this.description + "]";
};
JpegMeta.MetaProp = function MetaProp(fieldName, description, value) {
    this.fieldName = fieldName;
    this.description = description;
    this.value = value;
    return this;
};
JpegMeta.MetaProp.prototype.toString = function toString() {
    return "" + this.value;
};
JpegMeta.JpegFile = function JpegFile(binary_data, filename) {
    var break_segment = this._SOS;
    this.metaGroups = {};
    this._binary_data = binary_data;
    this.filename = filename;
    var pos = 0;
    var pos_start_of_segment = 0;
    var delim;
    var mark;
    var _mark;
    var segsize;
    var headersize;
    var mark_code;
    var mark_fn;
    if (this._binary_data.slice(0, 2) !== this._SOI_MARKER) {
        throw new Error("Doesn't look like a JPEG file. First two bytes are " + this._binary_data.charCodeAt(0) + "," + this._binary_data.charCodeAt(1) + ".");
    }
    pos += 2;
    while (pos < this._binary_data.length) {
        delim = this._binary_data.charCodeAt(pos++);
        mark = this._binary_data.charCodeAt(pos++);
        console.log(mark.toString(16))
        pos_start_of_segment = pos;
        if (delim != this._DELIM) {
            break;
        }
        if (mark === break_segment) {
            break;
        }
        headersize = JpegMeta.parseNum(">", this._binary_data, pos, 2);
        console.log('headsize=' + headersize)
        pos += headersize;
        while (pos < this._binary_data.length) {
            delim = this._binary_data.charCodeAt(pos++);
            if (delim == this._DELIM) {
                _mark = this._binary_data.charCodeAt(pos++);
                if (_mark != 0x0) {
                    pos -= 2;
                    break;
                }
            }
        }
        segsize = pos - pos_start_of_segment;
        if (this._markers[mark]) {
            mark_code = this._markers[mark][0];
            mark_fn = this._markers[mark][1];
        } else {
            mark_code = "UNKN";
            mark_fn = undefined;
        }
        if (mark_fn) {
            this[mark_fn](mark, pos_start_of_segment + 2);
        }
    }
    if (this.general === undefined) {
        throw Error("Invalid JPEG file.");
    }
    return this;
};
this.JpegMeta.JpegFile.prototype.toString = function() {
    return "[JpegFile " + this.filename + " " + this.general.type + " " + this.general.pixelWidth + "x" + this.general.pixelHeight + " Depth: " + this.general.depth + "]";
};
this.JpegMeta.JpegFile.prototype._SOI_MARKER = '\xff\xd8';
this.JpegMeta.JpegFile.prototype._DELIM = 0xff;
this.JpegMeta.JpegFile.prototype._EOI = 0xd9;
this.JpegMeta.JpegFile.prototype._SOS = 0xda;
this.JpegMeta.JpegFile.prototype._sofHandler = function _sofHandler(mark, pos) {
    if (this.general !== undefined) {
        throw Error("Unexpected multiple-frame image");
    }
    this._addMetaGroup("general", "General");
    this.general._addProperty("depth", "Depth", JpegMeta.parseNum(">", this._binary_data, pos, 1));
    this.general._addProperty("pixelHeight", "Pixel Height", JpegMeta.parseNum(">", this._binary_data, pos + 1, 2));
    this.general._addProperty("pixelWidth", "Pixel Width", JpegMeta.parseNum(">", this._binary_data, pos + 3, 2));
    this.general._addProperty("type", "Type", this._markers[mark][2]);
};
this.JpegMeta.JpegFile.prototype._JFIF_IDENT = "JFIF\x00";
this.JpegMeta.JpegFile.prototype._JFXX_IDENT = "JFXX\x00";
this.JpegMeta.JpegFile.prototype._EXIF_IDENT = "Exif\x00";
this.JpegMeta.JpegFile.prototype._types = {
    1: ["BYTE", 1],
    2: ["ASCII", 1],
    3: ["SHORT", 2],
    4: ["LONG", 4],
    5: ["RATIONAL", 8],
    6: ["SBYTE", 1],
    7: ["UNDEFINED", 1],
    8: ["SSHORT", 2],
    9: ["SLONG", 4],
    10: ["SRATIONAL", 8],
    11: ["FLOAT", 4],
    12: ["DOUBLE", 8]
};
this.JpegMeta.JpegFile.prototype._tifftags = {
    256: ["Image width", "ImageWidth"],
    257: ["Image height", "ImageLength"],
    258: ["Number of bits per component", "BitsPerSample"],
    259: ["Compression scheme", "Compression", {
        1: "uncompressed",
        6: "JPEG compression"
    }],
    262: ["Pixel composition", "PhotmetricInerpretation", {
        2: "RGB",
        6: "YCbCr"
    }],
    274: ["Orientation of image", "Orientation", {
        1: "Normal",
        2: "Reverse?",
        3: "Upside-down",
        4: "Upside-down Reverse",
        5: "90 degree CW",
        6: "90 degree CW reverse",
        7: "90 degree CCW",
        8: "90 degree CCW reverse"
    }],
    277: ["Number of components", "SamplesPerPixel"],
    284: ["Image data arrangement", "PlanarConfiguration", {
        1: "chunky format",
        2: "planar format"
    }],
    530: ["Subsampling ratio of Y to C", "YCbCrSubSampling"],
    531: ["Y and C positioning", "YCbCrPositioning", {
        1: "centered",
        2: "co-sited"
    }],
    282: ["X Resolution", "XResolution"],
    283: ["Y Resolution", "YResolution"],
    296: ["Resolution Unit", "ResolutionUnit", {
        2: "inches",
        3: "centimeters"
    }],
    273: ["Image data location", "StripOffsets"],
    278: ["Number of rows per strip", "RowsPerStrip"],
    279: ["Bytes per compressed strip", "StripByteCounts"],
    513: ["Offset to JPEG SOI", "JPEGInterchangeFormat"],
    514: ["Bytes of JPEG Data", "JPEGInterchangeFormatLength"],
    301: ["Transfer function", "TransferFunction"],
    318: ["White point chromaticity", "WhitePoint"],
    319: ["Chromaticities of primaries", "PrimaryChromaticities"],
    529: ["Color space transformation matrix coefficients", "YCbCrCoefficients"],
    532: ["Pair of black and white reference values", "ReferenceBlackWhite"],
    306: ["Date and time", "DateTime"],
    270: ["Image title", "ImageDescription"],
    271: ["Make", "Make"],
    272: ["Model", "Model"],
    305: ["Software", "Software"],
    315: ["Person who created the image", "Artist"],
    316: ["Host Computer", "HostComputer"],
    33432: ["Copyright holder", "Copyright"],
    34665: ["Exif tag", "ExifIfdPointer"],
    34853: ["GPS tag", "GPSInfoIfdPointer"]
};
this.JpegMeta.JpegFile.prototype._exiftags = {
    36864: ["Exif Version", "ExifVersion"],
    40960: ["FlashPix Version", "FlashpixVersion"],
    40961: ["Color Space", "ColorSpace"],
    37121: ["Meaning of each component", "ComponentsConfiguration"],
    37122: ["Compressed Bits Per Pixel", "CompressedBitsPerPixel"],
    40962: ["Pixel X Dimension", "PixelXDimension"],
    40963: ["Pixel Y Dimension", "PixelYDimension"],
    37500: ["Manufacturer notes", "MakerNote"],
    37510: ["User comments", "UserComment"],
    40964: ["Related audio file", "RelatedSoundFile"],
    36867: ["Date Time Original", "DateTimeOriginal"],
    36868: ["Date Time Digitized", "DateTimeDigitized"],
    37520: ["DateTime subseconds", "SubSecTime"],
    37521: ["DateTimeOriginal subseconds", "SubSecTimeOriginal"],
    37522: ["DateTimeDigitized subseconds", "SubSecTimeDigitized"],
    33434: ["Exposure time", "ExposureTime"],
    33437: ["FNumber", "FNumber"],
    34850: ["Exposure program", "ExposureProgram"],
    34852: ["Spectral sensitivity", "SpectralSensitivity"],
    34855: ["ISO Speed Ratings", "ISOSpeedRatings"],
    34856: ["Optoelectric coefficient", "OECF"],
    37377: ["Shutter Speed", "ShutterSpeedValue"],
    37378: ["Aperture Value", "ApertureValue"],
    37379: ["Brightness", "BrightnessValue"],
    37380: ["Exposure Bias Value", "ExposureBiasValue"],
    37381: ["Max Aperture Value", "MaxApertureValue"],
    37382: ["Subject Distance", "SubjectDistance"],
    37383: ["Metering Mode", "MeteringMode"],
    37384: ["Light Source", "LightSource"],
    37385: ["Flash", "Flash"],
    37386: ["Focal Length", "FocalLength"],
    37396: ["Subject Area", "SubjectArea"],
    41483: ["Flash Energy", "FlashEnergy"],
    41484: ["Spatial Frequency Response", "SpatialFrequencyResponse"],
    41486: ["Focal Plane X Resolution", "FocalPlaneXResolution"],
    41487: ["Focal Plane Y Resolution", "FocalPlaneYResolution"],
    41488: ["Focal Plane Resolution Unit", "FocalPlaneResolutionUnit"],
    41492: ["Subject Location", "SubjectLocation"],
    41493: ["Exposure Index", "ExposureIndex"],
    41495: ["Sensing Method", "SensingMethod"],
    41728: ["File Source", "FileSource"],
    41729: ["Scene Type", "SceneType"],
    41730: ["CFA Pattern", "CFAPattern"],
    41985: ["Custom Rendered", "CustomRendered"],
    41986: ["Exposure Mode", "Exposure Mode"],
    41987: ["White Balance", "WhiteBalance"],
    41988: ["Digital Zoom Ratio", "DigitalZoomRatio"],
    41990: ["Scene Capture Type", "SceneCaptureType"],
    41991: ["Gain Control", "GainControl"],
    41992: ["Contrast", "Contrast"],
    41993: ["Saturation", "Saturation"],
    41994: ["Sharpness", "Sharpness"],
    41995: ["Device settings description", "DeviceSettingDescription"],
    41996: ["Subject distance range", "SubjectDistanceRange"],
    42016: ["Unique image ID", "ImageUniqueID"],
    40965: ["Interoperability tag", "InteroperabilityIFDPointer"]
};
this.JpegMeta.JpegFile.prototype._gpstags = {
    0: ["GPS tag version", "GPSVersionID"],
    1: ["North or South Latitude", "GPSLatitudeRef"],
    2: ["Latitude", "GPSLatitude"],
    3: ["East or West Longitude", "GPSLongitudeRef"],
    4: ["Longitude", "GPSLongitude"],
    5: ["Altitude reference", "GPSAltitudeRef"],
    6: ["Altitude", "GPSAltitude"],
    7: ["GPS time (atomic clock)", "GPSTimeStamp"],
    8: ["GPS satellites usedd for measurement", "GPSSatellites"],
    9: ["GPS receiver status", "GPSStatus"],
    10: ["GPS mesaurement mode", "GPSMeasureMode"],
    11: ["Measurement precision", "GPSDOP"],
    12: ["Speed unit", "GPSSpeedRef"],
    13: ["Speed of GPS receiver", "GPSSpeed"],
    14: ["Reference for direction of movement", "GPSTrackRef"],
    15: ["Direction of movement", "GPSTrack"],
    16: ["Reference for direction of image", "GPSImgDirectionRef"],
    17: ["Direction of image", "GPSImgDirection"],
    18: ["Geodetic survey data used", "GPSMapDatum"],
    19: ["Reference for latitude of destination", "GPSDestLatitudeRef"],
    20: ["Latitude of destination", "GPSDestLatitude"],
    21: ["Reference for longitude of destination", "GPSDestLongitudeRef"],
    22: ["Longitude of destination", "GPSDestLongitude"],
    23: ["Reference for bearing of destination", "GPSDestBearingRef"],
    24: ["Bearing of destination", "GPSDestBearing"],
    25: ["Reference for distance to destination", "GPSDestDistanceRef"],
    26: ["Distance to destination", "GPSDestDistance"],
    27: ["Name of GPS processing method", "GPSProcessingMethod"],
    28: ["Name of GPS area", "GPSAreaInformation"],
    29: ["GPS Date", "GPSDateStamp"],
    30: ["GPS differential correction", "GPSDifferential"]
};
this.JpegMeta.JpegFile.prototype._markers = {
    0xc0: ["SOF0", "_sofHandler", "Baseline DCT"],
    0xc1: ["SOF1", "_sofHandler", "Extended sequential DCT"],
    0xc2: ["SOF2", "_sofHandler", "Progressive DCT"],
    0xc3: ["SOF3", "_sofHandler", "Lossless (sequential)"],
    0xc5: ["SOF5", "_sofHandler", "Differential sequential DCT"],
    0xc6: ["SOF6", "_sofHandler", "Differential progressive DCT"],
    0xc7: ["SOF7", "_sofHandler", "Differential lossless (sequential)"],
    0xc8: ["JPG", null, "Reserved for JPEG extensions"],
    0xc9: ["SOF9", "_sofHandler", "Extended sequential DCT"],
    0xca: ["SOF10", "_sofHandler", "Progressive DCT"],
    0xcb: ["SOF11", "_sofHandler", "Lossless (sequential)"],
    0xcd: ["SOF13", "_sofHandler", "Differential sequential DCT"],
    0xce: ["SOF14", "_sofHandler", "Differential progressive DCT"],
    0xcf: ["SOF15", "_sofHandler", "Differential lossless (sequential)"],
    0xc4: ["DHT", null, "Define Huffman table(s)"],
    0xcc: ["DAC", null, "Define arithmetic coding conditioning(s)"],
    0xd0: ["RST0", null, "Restart with modulo 8 count “0”"],
    0xd1: ["RST1", null, "Restart with modulo 8 count “1”"],
    0xd2: ["RST2", null, "Restart with modulo 8 count “2”"],
    0xd3: ["RST3", null, "Restart with modulo 8 count “3”"],
    0xd4: ["RST4", null, "Restart with modulo 8 count “4”"],
    0xd5: ["RST5", null, "Restart with modulo 8 count “5”"],
    0xd6: ["RST6", null, "Restart with modulo 8 count “6”"],
    0xd7: ["RST7", null, "Restart with modulo 8 count “7”"],
    0xd8: ["SOI", null, "Start of image"],
    0xd9: ["EOI", null, "End of image"],
    0xda: ["SOS", null, "Start of scan"],
    0xdb: ["DQT", null, "Define quantization table(s)"],
    0xdc: ["DNL", null, "Define number of lines"],
    0xdd: ["DRI", null, "Define restart interval"],
    0xde: ["DHP", null, "Define hierarchical progression"],
    0xdf: ["EXP", null, "Expand reference component(s)"],
    0xe0: ["APP0", "_app0Handler", "Reserved for application segments"],
    0xe1: ["APP1", "_app1Handler"],
    0xe2: ["APP2", null],
    0xe3: ["APP3", null],
    0xe4: ["APP4", null],
    0xe5: ["APP5", null],
    0xe6: ["APP6", null],
    0xe7: ["APP7", null],
    0xe8: ["APP8", null],
    0xe9: ["APP9", null],
    0xea: ["APP10", null],
    0xeb: ["APP11", null],
    0xec: ["APP12", null],
    0xed: ["APP13", null],
    0xee: ["APP14", null],
    0xef: ["APP15", null],
    0xf0: ["JPG0", null],
    0xf1: ["JPG1", null],
    0xf2: ["JPG2", null],
    0xf3: ["JPG3", null],
    0xf4: ["JPG4", null],
    0xf5: ["JPG5", null],
    0xf6: ["JPG6", null],
    0xf7: ["JPG7", null],
    0xf8: ["JPG8", null],
    0xf9: ["JPG9", null],
    0xfa: ["JPG10", null],
    0xfb: ["JPG11", null],
    0xfc: ["JPG12", null],
    0xfd: ["JPG13", null],
    0xfe: ["COM", null],
    0x01: ["JPG13", null]
};
this.JpegMeta.JpegFile.prototype._addMetaGroup = function _addMetaGroup(name, description) {
    var group = new JpegMeta.MetaGroup(name, description);
    this[group.fieldName] = group;
    this.metaGroups[group.fieldName] = group;
    return group;
};
this.JpegMeta.JpegFile.prototype._parseIfd = function _parseIfd(endian, _binary_data, base, ifd_offset, tags, name, description) {
    var num_fields = JpegMeta.parseNum(endian, _binary_data, base + ifd_offset, 2);
    var i, j;
    var tag_base;
    var tag_field;
    var type, type_field, type_size;
    var num_values;
    var value_offset;
    var value;
    var _val;
    var num;
    var den;
    var group;
    group = this._addMetaGroup(name, description);
    for (var i = 0; i < num_fields; i++) {
        tag_base = base + ifd_offset + 2 + (i * 12);
        tag_field = JpegMeta.parseNum(endian, _binary_data, tag_base, 2);
        console.log('tag-field=' + tag_field)
        type_field = JpegMeta.parseNum(endian, _binary_data, tag_base + 2, 2);
        num_values = JpegMeta.parseNum(endian, _binary_data, tag_base + 4, 4);
        value_offset = JpegMeta.parseNum(endian, _binary_data, tag_base + 8, 4);
        if (this._types[type_field] === undefined) {
            continue;
        }
        type = this._types[type_field][0];
        type_size = this._types[type_field][1];
        if (type_size * num_values <= 4) {
            value_offset = tag_base + 8;
        } else {
            value_offset = base + value_offset;
        }
        if (type == "UNDEFINED") {
            f = _binary_data.slice(value_offset, value_offset + num_values);
        } else if (type == "ASCII") {
            value = _binary_data.slice(value_offset, value_offset + num_values);
            value = value.split('\x00')[0];
        } else {
            value = new Array();
            for (j = 0; j < num_values; j++, value_offset += type_size) {
                if (type == "BYTE" || type == "SHORT" || type == "LONG") {
                    value.push(JpegMeta.parseNum(endian, _binary_data, value_offset, type_size));
                }
                if (type == "SBYTE" || type == "SSHORT" || type == "SLONG") {
                    value.push(JpegMeta.parseSnum(endian, _binary_data, value_offset, type_size));
                }
                if (type == "RATIONAL") {
                    num = JpegMeta.parseNum(endian, _binary_data, value_offset, 4);
                    den = JpegMeta.parseNum(endian, _binary_data, value_offset + 4, 4);
                    value.push(new JpegMeta.Rational(num, den));
                }
                if (type == "SRATIONAL") {
                    num = JpegMeta.parseSnum(endian, _binary_data, value_offset, 4);
                    den = JpegMeta.parseSnum(endian, _binary_data, value_offset + 4, 4);
                    value.push(new JpegMeta.Rational(num, den));
                }
                value.push();
            }
            if (num_values === 1) {
                value = value[0];
            }
        }
        if (tags[tag_field] !== undefined) {
            group._addProperty(tags[tag_field][1], tags[tag_field][0], value);
        }
    }
};
this.JpegMeta.JpegFile.prototype._jfifHandler = function _jfifHandler(mark, pos) {
    if (this.jfif !== undefined) {
        throw Error("Multiple JFIF segments found");
    }
    this._addMetaGroup("jfif", "JFIF");
    this.jfif._addProperty("version_major", "Version Major", this._binary_data.charCodeAt(pos + 5));
    this.jfif._addProperty("version_minor", "Version Minor", this._binary_data.charCodeAt(pos + 6));
    this.jfif._addProperty("version", "JFIF Version", this.jfif.version_major.value + "." + this.jfif.version_minor.value);
    this.jfif._addProperty("units", "Density Unit", this._binary_data.charCodeAt(pos + 7));
    this.jfif._addProperty("Xdensity", "X density", JpegMeta.parseNum(">", this._binary_data, pos + 8, 2));
    this.jfif._addProperty("Ydensity", "Y Density", JpegMeta.parseNum(">", this._binary_data, pos + 10, 2));
    this.jfif._addProperty("Xthumbnail", "X Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 12, 1));
    this.jfif._addProperty("Ythumbnail", "Y Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 13, 1));
};
this.JpegMeta.JpegFile.prototype._app0Handler = function app0Handler(mark, pos) {
    var ident = this._binary_data.slice(pos, pos + 5);
    if (ident == this._JFIF_IDENT) {
        this._jfifHandler(mark, pos);
    } else if (ident == this._JFXX_IDENT) {} else {}
};
this.JpegMeta.JpegFile.prototype._app1Handler = function _app1Handler(mark, pos) {
    var ident = this._binary_data.slice(pos, pos + 5);
    if (ident == this._EXIF_IDENT) {
        this._exifHandler(mark, pos + 6);
    } else {}
};
JpegMeta.JpegFile.prototype._exifHandler = function _exifHandler(mark, pos) {
    if (this.exif !== undefined) {
        throw new Error("Multiple JFIF segments found");
    }
    var endian;
    var magic_field;
    var ifd_offset;
    var primary_ifd, exif_ifd, gps_ifd;
    var endian_field = this._binary_data.slice(pos, pos + 2);
    if (endian_field === "II") {
        endian = "<";
    } else if (endian_field === "MM") {
        endian = ">";
    } else {
        throw new Error("Malformed TIFF meta-data. Unknown endianess: " + endian_field);
    }
    magic_field = JpegMeta.parseNum(endian, this._binary_data, pos + 2, 2);
    if (magic_field !== 42) {
        throw new Error("Malformed TIFF meta-data. Bad magic: " + magic_field);
    }
    ifd_offset = JpegMeta.parseNum(endian, this._binary_data, pos + 4, 4);
    this._parseIfd(endian, this._binary_data, pos, ifd_offset, this._tifftags, "tiff", "TIFF");
    if (this.tiff.ExifIfdPointer) {
        console.log('has pointer1')
        this._parseIfd(endian, this._binary_data, pos, this.tiff.ExifIfdPointer.value, this._exiftags, "exif", "Exif");
    }
    if (this.tiff.GPSInfoIfdPointer) {
        this._parseIfd(endian, this._binary_data, pos, this.tiff.GPSInfoIfdPointer.value, this._gpstags, "gps", "GPS");
        if (this.gps.GPSLatitude) {
            var latitude;
            latitude = this.gps.GPSLatitude.value[0].asFloat() + (1 / 60) * this.gps.GPSLatitude.value[1].asFloat() + (1 / 3600) * this.gps.GPSLatitude.value[2].asFloat();
            if (this.gps.GPSLatitudeRef.value === "S") {
                latitude = -latitude;
            }
            this.gps._addProperty("latitude", "Dec. Latitude", latitude);
        }
        if (this.gps.GPSLongitude) {
            var longitude;
            longitude = this.gps.GPSLongitude.value[0].asFloat() + (1 / 60) * this.gps.GPSLongitude.value[1].asFloat() + (1 / 3600) * this.gps.GPSLongitude.value[2].asFloat();
            if (this.gps.GPSLongitudeRef.value === "W") {
                longitude = -longitude;
            }
            this.gps._addProperty("longitude", "Dec. Longitude", longitude);
        }
    }
};

/*****jpeg.encoder.basic.js****/
function JPEGEncoder(quality) {
    var self = this;
    var fround = Math.round;
    var ffloor = Math.floor;
    var YTable = new Array(64);
    var UVTable = new Array(64);
    var fdtbl_Y = new Array(64);
    var fdtbl_UV = new Array(64);
    var YDC_HT;
    var UVDC_HT;
    var YAC_HT;
    var UVAC_HT;
    var bitcode = new Array(65535);
    var category = new Array(65535);
    var outputfDCTQuant = new Array(64);
    var DU = new Array(64);
    var byteout = [];
    var bytenew = 0;
    var bytepos = 7;
    var YDU = new Array(64);
    var UDU = new Array(64);
    var VDU = new Array(64);
    var clt = new Array(256);
    var RGB_YUV_TABLE = new Array(2048);
    var currentQuality;
    var ZigZag = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63];
    var std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
    var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
    var std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d];
    var std_ac_luminance_values = [0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];
    var std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
    var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
    var std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77];
    var std_ac_chrominance_values = [0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa];

    function initQuantTables(sf) {
        var YQT = [16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99];
        for (var i = 0; i < 64; i++) {
            var t = ffloor((YQT[i] * sf + 50) / 100);
            if (t < 1) { t = 1; } else if (t > 255) { t = 255; }
            YTable[ZigZag[i]] = t;
        }
        var UVQT = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99];
        for (var j = 0; j < 64; j++) {
            var u = ffloor((UVQT[j] * sf + 50) / 100);
            if (u < 1) { u = 1; } else if (u > 255) { u = 255; }
            UVTable[ZigZag[j]] = u;
        }
        var aasf = [1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958, 0.541196100, 0.275899379];
        var k = 0;
        for (var row = 0; row < 8; row++) {
            for (var col = 0; col < 8; col++) { fdtbl_Y[k] = (1.0 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
                fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));
                k++; }
        }
    }

    function computeHuffmanTbl(nrcodes, std_table) {
        var codevalue = 0;
        var pos_in_table = 0;
        var HT = new Array();
        for (var k = 1; k <= 16; k++) {
            for (var j = 1; j <= nrcodes[k]; j++) { HT[std_table[pos_in_table]] = [];
                HT[std_table[pos_in_table]][0] = codevalue;
                HT[std_table[pos_in_table]][1] = k;
                pos_in_table++;
                codevalue++; }
            codevalue *= 2;
        }
        return HT;
    }

    function initHuffmanTbl() { YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
        UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
        YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
        UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values); }

    function initCategoryNumber() {
        var nrlower = 1;
        var nrupper = 2;
        for (var cat = 1; cat <= 15; cat++) {
            for (var nr = nrlower; nr < nrupper; nr++) { category[32767 + nr] = cat;
                bitcode[32767 + nr] = [];
                bitcode[32767 + nr][1] = cat;
                bitcode[32767 + nr][0] = nr; }
            for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) { category[32767 + nrneg] = cat;
                bitcode[32767 + nrneg] = [];
                bitcode[32767 + nrneg][1] = cat;
                bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg; }
            nrlower <<= 1;
            nrupper <<= 1;
        }
    }

    function initRGBYUVTable() {
        for (var i = 0; i < 256; i++) { RGB_YUV_TABLE[i] = 19595 * i;
            RGB_YUV_TABLE[(i + 256) >> 0] = 38470 * i;
            RGB_YUV_TABLE[(i + 512) >> 0] = 7471 * i + 0x8000;
            RGB_YUV_TABLE[(i + 768) >> 0] = -11059 * i;
            RGB_YUV_TABLE[(i + 1024) >> 0] = -21709 * i;
            RGB_YUV_TABLE[(i + 1280) >> 0] = 32768 * i + 0x807FFF;
            RGB_YUV_TABLE[(i + 1536) >> 0] = -27439 * i;
            RGB_YUV_TABLE[(i + 1792) >> 0] = -5329 * i; } }

    function writeBits(bs) {
        var value = bs[0];
        var posval = bs[1] - 1;
        while (posval >= 0) {
            if (value & (1 << posval)) { bytenew |= (1 << bytepos); }
            posval--;
            bytepos--;
            if (bytepos < 0) {
                if (bytenew == 0xFF) { writeByte(0xFF);
                    writeByte(0); } else { writeByte(bytenew); }
                bytepos = 7;
                bytenew = 0;
            }
        }
    }

    function writeByte(value) { byteout.push(clt[value]); }

    function writeWord(value) { writeByte((value >> 8) & 0xFF);
        writeByte((value) & 0xFF); }

    function fDCTQuant(data, fdtbl) {
        var d0, d1, d2, d3, d4, d5, d6, d7;
        var dataOff = 0;
        var i;
        const I8 = 8;
        const I64 = 64;
        for (i = 0; i < I8; ++i) { d0 = data[dataOff];
            d1 = data[dataOff + 1];
            d2 = data[dataOff + 2];
            d3 = data[dataOff + 3];
            d4 = data[dataOff + 4];
            d5 = data[dataOff + 5];
            d6 = data[dataOff + 6];
            d7 = data[dataOff + 7];
            var tmp0 = d0 + d7;
            var tmp7 = d0 - d7;
            var tmp1 = d1 + d6;
            var tmp6 = d1 - d6;
            var tmp2 = d2 + d5;
            var tmp5 = d2 - d5;
            var tmp3 = d3 + d4;
            var tmp4 = d3 - d4;
            var tmp10 = tmp0 + tmp3;
            var tmp13 = tmp0 - tmp3;
            var tmp11 = tmp1 + tmp2;
            var tmp12 = tmp1 - tmp2;
            data[dataOff] = tmp10 + tmp11;
            data[dataOff + 4] = tmp10 - tmp11;
            var z1 = (tmp12 + tmp13) * 0.707106781;
            data[dataOff + 2] = tmp13 + z1;
            data[dataOff + 6] = tmp13 - z1;
            tmp10 = tmp4 + tmp5;
            tmp11 = tmp5 + tmp6;
            tmp12 = tmp6 + tmp7;
            var z5 = (tmp10 - tmp12) * 0.382683433;
            var z2 = 0.541196100 * tmp10 + z5;
            var z4 = 1.306562965 * tmp12 + z5;
            var z3 = tmp11 * 0.707106781;
            var z11 = tmp7 + z3;
            var z13 = tmp7 - z3;
            data[dataOff + 5] = z13 + z2;
            data[dataOff + 3] = z13 - z2;
            data[dataOff + 1] = z11 + z4;
            data[dataOff + 7] = z11 - z4;
            dataOff += 8; }
        dataOff = 0;
        for (i = 0; i < I8; ++i) { d0 = data[dataOff];
            d1 = data[dataOff + 8];
            d2 = data[dataOff + 16];
            d3 = data[dataOff + 24];
            d4 = data[dataOff + 32];
            d5 = data[dataOff + 40];
            d6 = data[dataOff + 48];
            d7 = data[dataOff + 56];
            var tmp0p2 = d0 + d7;
            var tmp7p2 = d0 - d7;
            var tmp1p2 = d1 + d6;
            var tmp6p2 = d1 - d6;
            var tmp2p2 = d2 + d5;
            var tmp5p2 = d2 - d5;
            var tmp3p2 = d3 + d4;
            var tmp4p2 = d3 - d4;
            var tmp10p2 = tmp0p2 + tmp3p2;
            var tmp13p2 = tmp0p2 - tmp3p2;
            var tmp11p2 = tmp1p2 + tmp2p2;
            var tmp12p2 = tmp1p2 - tmp2p2;
            data[dataOff] = tmp10p2 + tmp11p2;
            data[dataOff + 32] = tmp10p2 - tmp11p2;
            var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781;
            data[dataOff + 16] = tmp13p2 + z1p2;
            data[dataOff + 48] = tmp13p2 - z1p2;
            tmp10p2 = tmp4p2 + tmp5p2;
            tmp11p2 = tmp5p2 + tmp6p2;
            tmp12p2 = tmp6p2 + tmp7p2;
            var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433;
            var z2p2 = 0.541196100 * tmp10p2 + z5p2;
            var z4p2 = 1.306562965 * tmp12p2 + z5p2;
            var z3p2 = tmp11p2 * 0.707106781;
            var z11p2 = tmp7p2 + z3p2;
            var z13p2 = tmp7p2 - z3p2;
            data[dataOff + 40] = z13p2 + z2p2;
            data[dataOff + 24] = z13p2 - z2p2;
            data[dataOff + 8] = z11p2 + z4p2;
            data[dataOff + 56] = z11p2 - z4p2;
            dataOff++; }
        var fDCTQuant;
        for (i = 0; i < I64; ++i) { fDCTQuant = data[i] * fdtbl[i];
            outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5) | 0) : ((fDCTQuant - 0.5) | 0); }
        return outputfDCTQuant;
    }

    function writeAPP0() { writeWord(0xFFE0);
        writeWord(16);
        writeByte(0x4A);
        writeByte(0x46);
        writeByte(0x49);
        writeByte(0x46);
        writeByte(0);
        writeByte(1);
        writeByte(1);
        writeByte(0);
        writeWord(1);
        writeWord(1);
        writeByte(0);
        writeByte(0); }

    function writeSOF0(width, height) { writeWord(0xFFC0);
        writeWord(17);
        writeByte(8);
        writeWord(height);
        writeWord(width);
        writeByte(3);
        writeByte(1);
        writeByte(0x11);
        writeByte(0);
        writeByte(2);
        writeByte(0x11);
        writeByte(1);
        writeByte(3);
        writeByte(0x11);
        writeByte(1); }

    function writeDQT() {
        writeWord(0xFFDB);
        writeWord(132);
        writeByte(0);
        for (var i = 0; i < 64; i++) { writeByte(YTable[i]); }
        writeByte(1);
        for (var j = 0; j < 64; j++) { writeByte(UVTable[j]); }
    }

    function writeDHT() {
        writeWord(0xFFC4);
        writeWord(0x01A2);
        writeByte(0);
        for (var i = 0; i < 16; i++) { writeByte(std_dc_luminance_nrcodes[i + 1]); }
        for (var j = 0; j <= 11; j++) { writeByte(std_dc_luminance_values[j]); }
        writeByte(0x10);
        for (var k = 0; k < 16; k++) { writeByte(std_ac_luminance_nrcodes[k + 1]); }
        for (var l = 0; l <= 161; l++) { writeByte(std_ac_luminance_values[l]); }
        writeByte(1);
        for (var m = 0; m < 16; m++) { writeByte(std_dc_chrominance_nrcodes[m + 1]); }
        for (var n = 0; n <= 11; n++) { writeByte(std_dc_chrominance_values[n]); }
        writeByte(0x11);
        for (var o = 0; o < 16; o++) { writeByte(std_ac_chrominance_nrcodes[o + 1]); }
        for (var p = 0; p <= 161; p++) { writeByte(std_ac_chrominance_values[p]); }
    }

    function writeSOS() { writeWord(0xFFDA);
        writeWord(12);
        writeByte(3);
        writeByte(1);
        writeByte(0);
        writeByte(2);
        writeByte(0x11);
        writeByte(3);
        writeByte(0x11);
        writeByte(0);
        writeByte(0x3f);
        writeByte(0); }

    function processDU(CDU, fdtbl, DC, HTDC, HTAC) {
        var EOB = HTAC[0x00];
        var M16zeroes = HTAC[0xF0];
        var pos;
        const I16 = 16;
        const I63 = 63;
        const I64 = 64;
        var DU_DCT = fDCTQuant(CDU, fdtbl);
        for (var j = 0; j < I64; ++j) { DU[ZigZag[j]] = DU_DCT[j]; }
        var Diff = DU[0] - DC;
        DC = DU[0];
        if (Diff == 0) { writeBits(HTDC[0]); } else { pos = 32767 + Diff;
            writeBits(HTDC[category[pos]]);
            writeBits(bitcode[pos]); }
        var end0pos = 63;
        for (;
            (end0pos > 0) && (DU[end0pos] == 0); end0pos--) {};
        if (end0pos == 0) { writeBits(EOB);
            return DC; }
        var i = 1;
        var lng;
        while (i <= end0pos) {
            var startpos = i;
            for (;
                (DU[i] == 0) && (i <= end0pos); ++i) {}
            var nrzeroes = i - startpos;
            if (nrzeroes >= I16) {
                lng = nrzeroes >> 4;
                for (var nrmarker = 1; nrmarker <= lng; ++nrmarker)
                    writeBits(M16zeroes);
                nrzeroes = nrzeroes & 0xF;
            }
            pos = 32767 + DU[i];
            writeBits(HTAC[(nrzeroes << 4) + category[pos]]);
            writeBits(bitcode[pos]);
            i++;
        }
        if (end0pos != I63) { writeBits(EOB); }
        return DC;
    }

    function initCharLookupTable() {
        var sfcc = String.fromCharCode;
        for (var i = 0; i < 256; i++) { clt[i] = sfcc(i); } }
    this.encode = function(image, quality) {
        var time_start = new Date().getTime();
        if (quality) setQuality(quality);
        byteout = new Array();
        bytenew = 0;
        bytepos = 7;
        writeWord(0xFFD8);
        writeAPP0();
        writeDQT();
        writeSOF0(image.width, image.height);
        writeDHT();
        writeSOS();
        var DCY = 0;
        var DCU = 0;
        var DCV = 0;
        bytenew = 0;
        bytepos = 7;
        this.encode.displayName = "_encode_";
        var imageData = image.data;
        var width = image.width;
        var height = image.height;
        var quadWidth = width * 4;
        var tripleWidth = width * 3;
        var x, y = 0;
        var r, g, b;
        var start, p, col, row, pos;
        while (y < height) {
            x = 0;
            while (x < quadWidth) {
                start = quadWidth * y + x;
                p = start;
                col = -1;
                row = 0;
                for (pos = 0; pos < 64; pos++) {
                    row = pos >> 3;
                    col = (pos & 7) * 4;
                    p = start + (row * quadWidth) + col;
                    if (y + row >= height) { p -= (quadWidth * (y + 1 + row - height)); }
                    if (x + col >= quadWidth) { p -= ((x + col) - quadWidth + 4) }
                    r = imageData[p++];
                    g = imageData[p++];
                    b = imageData[p++];
                    YDU[pos] = ((RGB_YUV_TABLE[r] + RGB_YUV_TABLE[(g + 256) >> 0] + RGB_YUV_TABLE[(b + 512) >> 0]) >> 16) - 128;
                    UDU[pos] = ((RGB_YUV_TABLE[(r + 768) >> 0] + RGB_YUV_TABLE[(g + 1024) >> 0] + RGB_YUV_TABLE[(b + 1280) >> 0]) >> 16) - 128;
                    VDU[pos] = ((RGB_YUV_TABLE[(r + 1280) >> 0] + RGB_YUV_TABLE[(g + 1536) >> 0] + RGB_YUV_TABLE[(b + 1792) >> 0]) >> 16) - 128;
                }
                DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
                DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
                DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
                x += 32;
            }
            y += 8;
        }
        if (bytepos >= 0) {
            var fillbits = [];
            fillbits[1] = bytepos + 1;
            fillbits[0] = (1 << (bytepos + 1)) - 1;
            writeBits(fillbits); }
        writeWord(0xFFD9);
        var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));
        byteout = [];
        var duration = new Date().getTime() - time_start;
        console.log('Encoding time: ' + duration + 'ms');
        return jpegDataUri
    }

    function setQuality(quality) {
        if (quality <= 0) { quality = 1; }
        if (quality > 100) { quality = 100; }
        if (currentQuality == quality) return
        var sf = 0;
        if (quality < 50) { sf = Math.floor(5000 / quality); } else { sf = Math.floor(200 - quality * 2); }
        initQuantTables(sf);
        currentQuality = quality;
        console.log('Quality set to: ' + quality + '%');
    }

    function init() {
        var time_start = new Date().getTime();
        if (!quality) quality = 50;
        initCharLookupTable()
        initHuffmanTbl();
        initCategoryNumber();
        initRGBYUVTable();
        setQuality(quality);
        var duration = new Date().getTime() - time_start;
        console.log('Initialization ' + duration + 'ms');
    }
    init();
};

function getImageDataFromImage(idOrElement) {
    var theImg = (typeof(idOrElement) == 'string') ? document.getElementById(idOrElement) : idOrElement;
    var cvs = document.createElement('canvas');
    cvs.width = theImg.width;
    cvs.height = theImg.height;
    var ctx = cvs.getContext("2d");
    ctx.drawImage(theImg, 0, 0);
    return (ctx.getImageData(0, 0, cvs.width, cvs.height)); }
/*****image_compress.js**/
/**
 * 图片压缩静态类 from qzone
 */
var ImageCompresser = {
    /**
     * 检测ios平台是否有做过抽样处理
     * @param {Element} img
     */
    isIosSubSample: function(img) {
        var w = img.naturalWidth,
            h = img.naturalHeight,
            hasSubSample = false;
        if (w * h > 1024 * 1024) { //超过1K*1K分辨率的图会被抽样
            var canvas = document.createElement('canvas');
            ctx = canvas.getContext('2d'),
                canvas.width = canvas.height = 1;
            ctx.drawImage(img, 1 - w, 0);
            hasSubSample = ctx.getImageData(0, 0, 1, 1).data[3] === 0;
            canvas = ctx = null; //清理
        }
        return hasSubSample;
    },

    /**
     * 获取ios上图片被压缩比例
     * 随机使用1px宽度尝试绘制样图，估算原图被ios压缩了多少
     * @param {Element} img
     * @param {Number} w
     * @param {Number} h
     */
    getIosImageRatio: function(img, w, h) {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d'),
            data,
            sy = 0, //起始y坐标
            ey = h, //结束y坐标
            py = h; //当前判断的y坐标
        canvas.width = 1;
        canvas.height = h
        ctx.drawImage(img, 1 - Math.ceil(Math.random() * w), 0); //随机画1px宽度
        data = ctx.getImageData(0, 0, 1, h).data;
        while (py > sy) {
            var alpha = data[(py - 1) * 4 + 3]; //Notice:如果原图自带透明度，这里可能会失效
            if (alpha === 0) {
                ey = py;
            } else {
                sy = py;
            }
            py = (ey + sy) >> 1;
        }
        return py / h;
    },

    /**
     * 获取图片base64
     * @param {Elemnt} img
     * @param {opts} opts
     *      opts.maxW {Number}  目标图片最大宽度
     *      opts.maxH {Number}  目标图片最大高度
     *      quality {Number}    目标图片压缩质量
     *      orien {Number}      目标图片旋转方向
     */
    getImageBase64: function(img, opts) {

        //获取配置
        var maxW = opts.maxW, //图片最大限制
            maxH = opts.maxW,
            quality = opts.quality,
            _w = img.naturalWidth, //图片实际大小
            _h = img.naturalHeight,
            w, h; //图片目标大小

        var USER_AGENT = navigator.userAgent;
        var iphone = USER_AGENT.match(/(iPhone\sOS)\s([\d_]+)/);
        var android = USER_AGENT.match(/(Android)\s+([\d.]+)/);

        //ios平台针对大图做抽值处理
        if (iphone && ImageCompresser.isIosSubSample(img)) {
            _w = _w / 2;
            _h = _h / 2;
        }
        //获取最终生成图片大小
        if (_w > maxW && _w / _h >= maxW / maxH) {
            w = maxW;
            h = _h * maxW / _w;
        } else if (_h > maxH && _h / _w >= maxH / maxW) {
            w = _w * maxH / _h;
            h = maxH;
        } else {
            w = _w;
            h = _h;
        }
        //canvas临时工具
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d'),
            base64Str;
        this.doAutoRotate(canvas, w, h, opts.orien);
        //ios平台贴瓷砖处理大图片
        if (iphone) {
            var tmpCanvas = document.createElement('canvas'),
                tmpCtx = tmpCanvas.getContext('2d'),
                d = 1024, //瓷砖canvas的大小
                vertSquashRatio = ImageCompresser.getIosImageRatio(img, _w, _h), //ios平台大尺寸图片压缩比
                sx, sy, sw, sh, dx, dy, dw, dh;
            tmpCanvas.width = tmpCanvas.height = d;
            sy = 0;
            while (sy < _h) {
                sh = sy + d > _h ? _h - sy : d,
                    sx = 0;
                while (sx < _w) {
                    sw = sx + d > _w ? _w - sx : d;
                    tmpCtx.clearRect(0, 0, d, d);
                    tmpCtx.drawImage(img, -sx, -sy);
                    dx = Math.floor(sx * w / _w);
                    dw = Math.ceil(sw * w / _w);
                    dy = Math.floor(sy * h / _h / vertSquashRatio);
                    dh = Math.ceil(sh * h / _h / vertSquashRatio);
                    ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh);
                    sx += d;
                }
                sy += d;
            }
            tmpCanvas = tmpCtx = null;
        } else {
            ctx.drawImage(img, 0, 0, _w, _h, 0, 0, w, h);
        }
        //android平台调用jpegEncoder处理生成jpg压缩格式
        if (android) {
            var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height),
                encoder = new JPEGEncoder(quality * 100);
            base64Str = encoder.encode(imgData);
            encoder = null;
        } else {
            base64Str = canvas.toDataURL('image/jpeg', quality);
        }

        // console.log(base64Str);
        canvas = ctx = null;
        return base64Str;
    },
    /**
     * 旋转图片
     * @param {Element} canvas 画布
     * @param {Number} width 宽度
     * @param {Number} height 高度
     * @param {Number} orientation 旋转角度[1|2|3|4|5|6|7|8]
     */
    doAutoRotate: function(canvas, width, height, orientation) {
        var ctx = canvas.getContext('2d');
        if (orientation >= 5 && orientation <= 8) {
            canvas.width = height;
            canvas.height = width;
        } else {
            canvas.width = width;
            canvas.height = height;
        }
        switch (orientation) {
            case 2:
                // horizontal flip
                ctx.translate(width, 0);
                ctx.scale(-1, 1);
                break;
            case 3:
                // 180 rotate left
                ctx.translate(width, height);
                ctx.rotate(Math.PI);
                break;
            case 4:
                // vertical flip
                ctx.translate(0, height);
                ctx.scale(1, -1);
                break;
            case 5:
                // vertical flip + 90 rotate right
                ctx.rotate(0.5 * Math.PI);
                ctx.scale(1, -1);
                break;
            case 6:
                // 90 rotate right
                ctx.rotate(0.5 * Math.PI);
                ctx.translate(0, -height);
                break;
            case 7:
                // horizontal flip + 90 rotate right
                ctx.rotate(0.5 * Math.PI);
                ctx.translate(width, -height);
                ctx.scale(-1, 1);
                break;
            case 8:
                // 90 rotate left
                ctx.rotate(-0.5 * Math.PI);
                ctx.translate(-width, 0);
                break;
            default:
                break;
        }
    },
    /**
     * 获取文件地址
     * @param {File} file
     */
    getFileObjectURL: function(file) {
        var URL = window.URL || window.webkitURL || false;
        if (URL) {
            return URL.createObjectURL(file);
        }
    },

    /**
     * 是否支持本地压缩
     */
    support: function() {
        return typeof(window.File) && typeof(window.FileList) && typeof(window.FileReader) && typeof(window.Blob);
    }
};
